package com.alibaba.citrus.cr.order.open.api.facade.transfer;

import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.order.open.api.facade.common.model.ShippingOrderCreatedMessageData;
import com.alibaba.citrus.cr.order.open.api.facade.common.model.ShippingOrderCreatedMessageDataLine;
import com.alibaba.citrus.cr.order.open.api.facade.common.model.WmsOutBoundMessage;
import com.alibaba.citrus.cr.order.open.api.facade.model.TransferOrder;
import com.alibaba.citrus.cr.order.open.api.facade.model.TransferOrderQueryRequest;
import com.alibaba.citrus.cr.order.open.api.facade.model.TransferSubOrder;
import com.alibaba.citrus.cr.order.open.api.facade.transferorder.TransferOrderQueryService;
import com.alibaba.citrus.cr.unified.inventory.contants.FeaturesKey;
import com.alibaba.citrus.cr.unified.inventory.utils.ToolUtil;
import com.alibaba.citrus.cr.unified.inventory.utils.WarehouseConverter;
import com.alibaba.cloud.retail.delivery.api.model.delivery.enums.FulfillmentDirectionTypeEnum;
import com.alibaba.cloud.retail.delivery.api.model.delivery.enums.FulfillmentTypeEnum;
import com.alibaba.cloud.retail.delivery.api.model.delivery.enums.OrderTypeEnum;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.BcShipOrderGetReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.BcShipOrderQueryReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.CreateFulfillmentOrderDetailDTO;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.CreateFulfillmentOrderReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.SearchBcShipOrderReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.UpdateFulfillmentOrderDetailFeaturesReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.UpdateFulfillmentOrderFeaturesReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.BcShipOrderQueryRes;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.BcShipOrderSearchRes;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentGetRes;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentOrderResponse;
import com.alibaba.cloud.retail.delivery.api.model.fulfillment.request.SearchFulfullmentOrderReq;
import com.alibaba.cloud.retail.delivery.api.service.bcfulfillment.BcShipOrderAbilityService;
import com.alibaba.cloud.retail.delivery.api.service.bcfulfillment.FulfillmentOrderAbilityService;
import com.alibaba.cloud.retail.store.api.service.CargoZoneQueryService;
import com.alibaba.cloud.retail.store.request.cargozone.QueryCargoZoneRequest;
import com.alibaba.cloud.retail.store.response.ResultPager;
import com.alibaba.cloud.retail.wms.api.model.orders.common.WarehousingOrderDTO;
import com.alibaba.cloud.retail.wms.api.model.orders.common.WarehousingSubOrderDTO;
import com.alibaba.cloud.retail.wms.api.model.orders.request.WarehousingOrdersQueryRequest;
import com.alibaba.cloud.retail.wms.api.model.orders.response.WarehousingOrderQueryResponse;
import com.alibaba.cloud.retail.wms.api.service.orders.WarehousingOrderReadService;
import com.alibaba.cz.base.model.store.CargoZoneSDO;
import com.alibaba.cz.base.tool.DateFormatUtil;
import com.alibaba.cz.base.tool.FeatureUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crunifiedinventory.sdo.enums.AllocateOrderShipTypeEnums;
import com.epoch.app.crunifiedinventory.sdo.enums.AllocateOrderTypeEnum;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: yuhw
 * @date: 2024年01月09日 14:42
 **/
@Component
public class CreateFulfillmentOrderReqFactory {
    private static Log log = Log.getLogger(CreateFulfillmentOrderReqFactory.class);

    @Resource
    private TransferOrderQueryService transferOrderQueryService;
    @DubboReference
    private WarehousingOrderReadService warehousingOrderReadService;
    @Resource
    private WarehouseConverter warehouseConverter;
    @DubboReference
    private CargoZoneQueryService cargoZoneQueryService;
    @DubboReference(protocol = "dubbo", check = false)
    private FulfillmentOrderAbilityService fulfillmentOrderAbilityService;
    @DubboReference
    private BcShipOrderAbilityService bcShipOrderAbilityService;
    //出库单子单号
    private static final String WMS_SUB_ORDER_ID = "wmsSubOrderId";
    //出库单主单号
    private static final String WMS_ORDER_ID = "wmsOrderId";
    //纯汽运
    private static final String Z001 = "Z001";
    //汽运上站
    private static final String Z002 = "Z002";
    //铁运装运单
    private static final String Z004 = "Z004";
    //海运装运单
    private static final String Z005 = "Z005";

    //因装运单消息的每个明细都需要创建履约单,所以获取的是批量请求
    public List<CreateFulfillmentOrderReq> batchBuild(ShippingOrderCreatedMessageData messageData){
        List<CreateFulfillmentOrderReq> reqList = Lists.newArrayList();
        if (Objects.isNull(messageData) || StringUtils.isBlank(messageData.getOrderNo()) || CollectionUtils.isEmpty(messageData.getOrderLine())){
            return reqList;
        }
        messageData.getOrderLine().forEach(line -> {
            //TODO 这里需要判断下是否该接消息
            // 通过出库单号查询当前逆向履约单是否创建(幂等)
            if (StringUtils.isBlank(line.getOutboundOrderNo())) {
                log.error("CreateFulfillmentOrderReqFactory_batchBuild_outboundOrderNo_is_null");
                return;
            }
            List<FulfillmentGetRes> fulfillmentInfo = getFulfillmentInfo(line.getOutboundOrderNo());
            if (CollectionUtils.isNotEmpty(fulfillmentInfo)) {
                return;
            }
            CreateFulfillmentOrderReq req = this.build(messageData, line);
            if (req != null){
                reqList.add(req);
            }
        });
        return reqList;
    }

    public CreateFulfillmentOrderReq build(ShippingOrderCreatedMessageData messageData,
                                           ShippingOrderCreatedMessageDataLine detailMessage){
        CreateFulfillmentOrderReq req = new CreateFulfillmentOrderReq();
        //TODO 这一步有可能 往外调一阵 查出入库单信息
        WarehousingOrdersQueryRequest wmsOrderQueryRequest = new WarehousingOrdersQueryRequest();
        wmsOrderQueryRequest.setWmsOrderId(detailMessage.getOutboundOrderNo());
        wmsOrderQueryRequest.setIncludeFeatures(Boolean.FALSE);
//        String wmsOrderId = detailMessage.getOutboundOrderNo();
//        com.alibaba.cz.base.tool.result.Result<WarehousingOrdersQueryResponse> wmsOrder = warehousingOrderReadService.queryWarehousingOrder(wmsOrderId);
        com.alibaba.cz.base.tool.result.Result<WarehousingOrderQueryResponse> wmsOrder = warehousingOrderReadService.searchWmsOrder(wmsOrderQueryRequest);
        log.info("searchWmsOrder_result:{}",JSON.toJSONString(wmsOrder));
//        if (Objects.isNull(wmsOrder) || Objects.isNull(wmsOrder.getResult()) || CollectionUtils.isEmpty(wmsOrder.getResult().getWarehousingOrder())){
        if (Objects.isNull(wmsOrder) || Objects.isNull(wmsOrder.getResult()) || wmsOrder.getResult().getWarehousingOrder() == null
            ||CollectionUtils.isEmpty(wmsOrder.getResult().getWarehousingOrder().getWmsSubOrders())){
            throw new FacadeException("OTS-03-005-00-15-203");
        }
//        List<WarehousingOrderDTO> warehousingOrders = wmsOrder.getResult().getWarehousingOrder().getWmsSubOrders();
        WarehousingOrderDTO orderDTO = wmsOrder.getResult().getWarehousingOrder();
        //鉴于履约单有收发货仓, 这里还是需要查询到调拨单
        TransferOrderQueryRequest transferOrderQueryRequest = new TransferOrderQueryRequest();

        String outAllocateOrderId;
        String transferOrderCode;
        //TODO 用消息上的
        if (StringUtils.isNotBlank(orderDTO.getBizOrderId())){
            transferOrderCode = orderDTO.getBizOrderId();
            transferOrderQueryRequest.setTransferOrderCode(transferOrderCode);
        }else {
            outAllocateOrderId = StringUtils.isNotBlank(detailMessage.getOutAllocateOrderId()) ?
                    detailMessage.getOutAllocateOrderId() : detailMessage.getOutSourceOrderId();
            transferOrderQueryRequest.setOutTransferOrderCode(outAllocateOrderId);
        }

        Result<TransferOrder> transferOrderResult = transferOrderQueryService.query(transferOrderQueryRequest);
        if (transferOrderResult == null || transferOrderResult.getResult() == null){
            throw new FacadeException("OTS-03-005-00-15-066");
        }
        TransferOrder transferOrder = transferOrderResult.getResult();
        //
        if (Arrays.asList(com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum.CURRENT2CURRENT,
                com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum.PILOT2CURRENT).stream()
                .anyMatch(fulfillmentTypeEnum -> fulfillmentTypeEnum.getValue().toString().equals(transferOrder.getFulfillmentTypeCode()))){
            throw new FacadeException("OTS-03-005-00-15-241");
        }
        //计划调拨 铁运需要接到铁运的才创建逆向履约单
        if (AllocateOrderTypeEnum.PLAN.getType().toString().equals(transferOrder.getTransferOrderType())
                && !Boolean.TRUE.equals(transferOrder.getReturnOrder())){
            //查询一下装运单信息
            SearchBcShipOrderReq searchBcShipOrderReq = new SearchBcShipOrderReq();
            searchBcShipOrderReq.setShipOrderNo(messageData.getOrderNo());
            com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result<List<BcShipOrderSearchRes>> shipOrder = bcShipOrderAbilityService.searchShipOrder(searchBcShipOrderReq);
            if (shipOrder == null || CollectionUtils.isEmpty(shipOrder.getResult())){
                throw new FacadeException("OTS-03-005-00-15-256");
            }
//            if (ToolUtil.isTrain(transferOrder.getShipMethod())){
//                if (Optional.ofNullable(shipOrder).map(com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result::getResult).orElse(Lists.newArrayList())
//                        .stream().noneMatch(bcShipOrderSearchRes -> Z004.equals(bcShipOrderSearchRes.getShippingType()))) {
//                    throw new FacadeException("OTS-03-005-00-15-256","铁运");
//                }
//            }
//            if (ToolUtil.isSea(transferOrder.getShipMethod())){
//                if (Optional.ofNullable(shipOrder).map(com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result::getResult).orElse(Lists.newArrayList())
//                        .stream().noneMatch(bcShipOrderSearchRes -> Z005.equals(bcShipOrderSearchRes.getShippingType()))) {
//                    throw new FacadeException("OTS-03-005-00-15-256","海运");
//                }
//            }
//            if (AllocateOrderShipTypeEnums.CAR.getType().equals(transferOrder.getShipMethod())){
//                if (Optional.ofNullable(shipOrder).map(com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result::getResult).orElse(Lists.newArrayList())
//                        .stream().noneMatch(bcShipOrderSearchRes -> Z001.equals(bcShipOrderSearchRes.getShippingType()))) {
//                    throw new FacadeException("OTS-03-005-00-15-256","汽运");
//                }
//            }

        }
        req.setFromSys(StringUtils.isNotBlank(orderDTO.getFromSys()) ? orderDTO.getFromSys() : "APP_SAP");
        req.setBusinessType(StringUtils.isNotBlank(orderDTO.getBusinessType()) ? orderDTO.getBusinessType() :"11");
        req.setBusinessUnitCode("6000");
        req.setRequestNo(UUID.randomUUID().toString().replaceAll("-",""));
        req.setSourceOrderNo(detailMessage.getOutboundOrderNo());
        if (Boolean.TRUE.equals(transferOrder.getReturnOrder())){
            req.setRefOrderType(OrderTypeEnum.ALLOCATE_RETURN_INBOUND.getValue());
        }else {
            req.setRefOrderType(OrderTypeEnum.ALLOCATE_INBOUND.getValue().toString());
        }
        // 判断虚拟移库 用调拨的仓判断
        if (com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum.VIRTUAL_TRANSFER.getValue().toString().equals(transferOrder.getFulfillmentTypeCode())){
            req.setFulfillmentType(FulfillmentTypeEnum.EXTERNALWAREHOUSE_FULFILLMENT.getValue());
            throw new FacadeException("OTS-03-005-00-15-240");
        }else {
            req.setFulfillmentType(FulfillmentTypeEnum.BIGWAREHOUSE_FULFILLMENT.getValue());
        }
        req.setAutoSubmit(Boolean.TRUE);
        //优先级哪里来
        req.setPriority(transferOrder.getPriority() == null ? "1" : transferOrder.getPriority());
        req.setProductGroupCode(transferOrder.getProductGroupCode());

//        Map<String, CargoZoneSDO> cargoZoneSDOMap = warehouseConverter.getCargoZoneSDOMap(Arrays.asList(transferOrder.getShipAreaId(), transferOrder.getReceiveAreaId(), transferOrder.getTransferWarehouseId())
//                .stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()));
        Map<String, CargoZoneSDO> cargoZoneSDOMap = getCargoZoneSDOMap(Arrays.asList(transferOrder.getShipAreaId(), transferOrder.getReceiveAreaId(), transferOrder.getShipWarehouseId(),transferOrder.getReceiveWarehouseId())
                .stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()));
        log.info("getCargoZoneSDOMap_result:{}",JSON.toJSONString(cargoZoneSDOMap));
        Map<String, CargoZoneSDO> codeZoneSDOMap = getCargoZoneSDOMapByCodes(Arrays.asList(transferOrder.getTransferWarehouseId()).stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()));
        //货场仓及退仓
        String logicShippingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipAreaId())).map(CargoZoneSDO::getCode).orElse(null);
        String logicShippingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipAreaId())).map(CargoZoneSDO::getName).orElse(null);
        String shippingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipWarehouseId())).map(CargoZoneSDO::getCode).orElse(null);
        String shippingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipWarehouseId())).map(CargoZoneSDO::getName).orElse(null);
        String logicReceivingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveAreaId())).map(CargoZoneSDO::getCode).orElse(null);
        String logicReceivingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveAreaId())).map(CargoZoneSDO::getName).orElse(null);
        String receivingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveWarehouseId())).map(CargoZoneSDO::getCode).orElse(null);
        String receivingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveWarehouseId())).map(CargoZoneSDO::getName).orElse(null);
        String transferWarehouseName = Optional.ofNullable(codeZoneSDOMap.get(transferOrder.getTransferWarehouseId())).map(CargoZoneSDO::getName).orElse(null);
        Map<String,String> mainFeatures = Maps.newHashMap();
        mainFeatures.put(FeaturesKey.OUT_ALLOCATE_ORDER_ID,transferOrder.getOutAllocateOrderId());
        //交货单号
        mainFeatures.put(FeaturesKey.DELIVERY_ORDER_ID,orderDTO.getDeliveryOrderId());
        if (Boolean.TRUE.equals(transferOrder.getReturnOrder())){
            req.setLogicReceivingWarehouseCode(logicShippingWarehouseCode);
            req.setLogicReceivingWarehouse(logicShippingWarehouseName);
            req.setReceivingWarehouseCode(shippingWarehouseCode);
            req.setReceivingWarehouse(shippingWarehouseName);
            mainFeatures.put(FeaturesKey.TRANSFER_ORDER_TARGET_LOGIC_WAREHOUSE_CODE,logicShippingWarehouseCode);
            if (ToolUtil.isTrainOrSea(transferOrder.getShipMethod())){
                req.setLogicShippingWarehouseCode(transferOrder.getTransferWarehouseId());
                req.setLogicShippingWarehouse(transferWarehouseName);
            }else {
                req.setLogicShippingWarehouseCode(logicReceivingWarehouseCode);
                req.setLogicShippingWarehouse(logicReceivingWarehouseName);
                req.setShippingWarehouseCode(receivingWarehouseCode);
                req.setShippingWarehouse(receivingWarehouseName);
            }
            CargoZoneSDO cargoZoneSDO = cargoZoneSDOMap.get(transferOrder.getReceiveAreaId());
            if (cargoZoneSDO != null && cargoZoneSDO.getFeature() != null){
                req.setSoldToPartyCode(cargoZoneSDO.getFeature().get("sapInternalSalesBPCode"));
                req.setShipToPartyCode(cargoZoneSDO.getFeature().get("sapInternalDeliveryBPCode"));
            }
        }else {
            req.setLogicShippingWarehouseCode(logicShippingWarehouseCode);
            req.setLogicShippingWarehouse(logicShippingWarehouseName);
            req.setShippingWarehouseCode(shippingWarehouseCode);
            req.setShippingWarehouse(shippingWarehouseName);
            mainFeatures.put(FeaturesKey.TRANSFER_ORDER_TARGET_LOGIC_WAREHOUSE_CODE,logicReceivingWarehouseCode);
            if (ToolUtil.isTrainOrSea(transferOrder.getShipMethod())){
                req.setLogicReceivingWarehouseCode(transferOrder.getTransferWarehouseId());
                req.setLogicReceivingWarehouse(transferWarehouseName);
            }else {
                req.setLogicReceivingWarehouseCode(logicReceivingWarehouseCode);
                req.setLogicReceivingWarehouse(logicReceivingWarehouseName);
                req.setReceivingWarehouseCode(receivingWarehouseCode);
                req.setReceivingWarehouse(receivingWarehouseName);
            }
            CargoZoneSDO cargoZoneSDO = cargoZoneSDOMap.get(transferOrder.getReceiveAreaId());
            if (cargoZoneSDO != null && cargoZoneSDO.getFeature() != null){
                req.setSoldToPartyCode(cargoZoneSDO.getFeature().get("sapInternalSalesBPCode"));
                req.setShipToPartyCode(cargoZoneSDO.getFeature().get("sapInternalDeliveryBPCode"));
            }
        }

        if (MapUtils.isNotEmpty(transferOrder.getBizFeatures())){
            if (StringUtils.isNotBlank(transferOrder.getBizFeatures().get(FeaturesKey.TRANSFER_OUT_BIZ_UNIT))){
                mainFeatures.put(FeaturesKey.TRANSFER_OUT_BIZ_UNIT,transferOrder.getBizFeatures().get(FeaturesKey.TRANSFER_OUT_BIZ_UNIT));
            }
            if (StringUtils.isNotBlank(transferOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT))){
                mainFeatures.put(FeaturesKey.BIZ_UNIT,transferOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT));
            }
        }
        if (MapUtils.isNotEmpty(mainFeatures)){
            req.setFeatures(FeatureUtil.toString(mainFeatures));
            req.setBizFeatures(JSONObject.toJSONString(mainFeatures));
        }
        req.setProductGroupCode(StringUtils.isNotBlank(transferOrder.getProductGroup()) ? transferOrder.getProductGroup() : "11");
        req.setChannelCode("90");
        //6000?
        req.setSalesOrganizationCode("6000");
        req.setExpectedDeliveryTime(Objects.isNull(transferOrder.getExpectedDeliveryDate()) ? null :
                DateFormatUtil.toString(transferOrder.getExpectedDeliveryDate(),"yyyy-MM-dd HH:mm:ss"));
        req.setShippingMethodCode(transferOrder.getShipMethod() == null ? null : transferOrder.getShipMethod().toString());
        req.setRemark(transferOrder.getRemark());

        //逆向履约单字段
        req.setShipOrderNo(messageData.getOrderNo());
        req.setContainerNo(messageData.getContainerNo());
        req.setDiverMobile(messageData.getDiverMobile());
        req.setExpectedArrivalTime(messageData.getExpectedDeliveryTime());
        /** 以上为逆向履约单传递字段 **/
        List<CreateFulfillmentOrderDetailDTO> detailDTOList = Lists.newArrayList();
        //获取到调拨单明细 筛选出出库单上,且是履约单上的明细用来创建逆向
        for (WarehousingSubOrderDTO wmsSubOrder : orderDTO.getWmsSubOrders()) {
            /**
             * 1.出库单明细上的业务单据行号
             * 2.出入库单明细上的外部单据行号
             */

            String outAllocateOrderLineId = StringUtils.isBlank(wmsSubOrder.getFeatureMap().get("outSourceOrderLineId")) ?
                    wmsSubOrder.getFeatureMap().get("outAllocateOrderLineId") :wmsSubOrder.getFeatureMap().get("outAllocateOrderLineId");
            String bizSubOrderId = wmsSubOrder.getBizSubOrderId();
            TransferSubOrder transferSubOrder = null;
            if (StringUtils.isNotBlank(bizSubOrderId)){
                transferSubOrder = transferOrder.getDetailList().stream().filter(detail -> Objects.equals(detail.getLineNo(),bizSubOrderId))
                        .findFirst().orElse(null);
            }else if (StringUtils.isNotBlank(outAllocateOrderLineId)){
                transferSubOrder = transferOrder.getDetailList().stream().filter(detail -> Objects.equals(detail.getOutAllocateOrderLineId(),outAllocateOrderLineId))
                        .findFirst().orElse(null);
            }
            if (transferSubOrder == null){
                //TODO error
                log.error("not_match_wms_sub_order:{}",JSON.toJSONString(wmsSubOrder));
                continue;
            }
            //履约子单
            CreateFulfillmentOrderDetailDTO detailReq = new CreateFulfillmentOrderDetailDTO();
            detailReq.setSourceOrderLineNo(transferSubOrder.getLineNo());
            detailReq.setRefOrderNo(transferOrder.getTransferOrderCode());
            detailReq.setRefOrderLineNo(transferSubOrder.getLineNo() == null ? null : transferSubOrder.getLineNo());
            detailReq.setMaterialCode(transferSubOrder.getMaterialCode());
//            detailReq.setRefOrderCreateTime(transferSubOrder.getOrderCreateTime());
            detailReq.setRefOrderCreateTime(transferSubOrder.getGmtCreate() == null ? null :
                    DateFormatUtil.toString(transferSubOrder.getGmtCreate(),"yyyy-MM-dd HH:mm:ss"));
//            detailReq.setProductionDate(transferSubOrder.getProductionDate());
            detailReq.setProductionDate(wmsSubOrder.getDom() != null ? DateFormatUtil.formatToyyyMMdd(wmsSubOrder.getDom()) : null);
//            detailReq.setSaleQuantity(new BigDecimal(wmsSubOrder.getGoodsQuantity()).movePointLeft(3));
            detailReq.setSaleQuantity(new BigDecimal(transferSubOrder.getQuantity().trim()));
            detailReq.setSalesUnitCode(transferSubOrder.getUnit());
            detailReq.setQuantity(new BigDecimal(wmsSubOrder.getGoodsQuantity()).movePointLeft(3));
            detailReq.setShippedQuantity(new BigDecimal(wmsSubOrder.getGoodsQuantity()).movePointLeft(3));
            detailReq.setShippingUnit(transferSubOrder.getUnit());
            detailReq.setShippingUnitCode(transferSubOrder.getUnit());
            detailReq.setRemark(transferSubOrder.getLineRemark());
            detailReq.setClose(Boolean.TRUE.equals(transferSubOrder.getClose()) ? 1 : 0);
            detailReq.setCloseReasonCode(transferSubOrder.getCloseReasonCode());
            detailReq.setCloseReason(transferSubOrder.getCloseReason());
            detailReq.setBatchNo(wmsSubOrder.getBatchNo());
            //TODO 写出库单的子单号的wms生成的
            Map<String,String> features = Maps.newHashMap();
            if (StringUtils.isNotBlank(wmsSubOrder.getWmsSubOrderId())){
                features.put(WMS_SUB_ORDER_ID,wmsSubOrder.getWmsSubOrderId());
            }
            if (StringUtils.isNotBlank(orderDTO.getWarehousingOrderId())){
                features.put(WMS_ORDER_ID,orderDTO.getWarehousingOrderId());
            }
            if (StringUtils.isNotBlank(transferSubOrder.getOutAllocateOrderLineId())){
                features.put(FeaturesKey.OUT_ALLOCATE_ORDER_LINE_ID,transferSubOrder.getOutAllocateOrderLineId());
            }
            Map<String, String> wmsSubFeatureMap = MapUtils.isNotEmpty(wmsSubOrder.getFeatureMap()) ? wmsSubOrder.getFeatureMap() : Maps.newHashMap();
            if (StringUtils.isNotBlank(wmsSubFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO))){
                features.put(FeaturesKey.FULL_SAP_BATCH_NO,wmsSubFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO));
            }
            JSONObject bizFeaturesJsonObject = new JSONObject();
            if (MapUtils.isNotEmpty(transferSubOrder.getBizFeatures())){
                features.put(FeaturesKey.BIZ_UNIT_RATIO,transferSubOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT_RATIO));
                if (StringUtils.isNotBlank(transferSubOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT_RATIO))){
                    bizFeaturesJsonObject.put(FeaturesKey.BIZ_UNIT_RATIO,transferSubOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT_RATIO));
                }
            }
            if (StringUtils.isNotBlank(wmsSubFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO))){
                bizFeaturesJsonObject.put(FeaturesKey.FULL_SAP_BATCH_NO,wmsSubFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO));
            }
            if (!bizFeaturesJsonObject.isEmpty()){
                detailReq.setBizFeatures(bizFeaturesJsonObject.toJSONString());
            }

            detailReq.setFeatures(FeatureUtil.toString(features));
            detailDTOList.add(detailReq);
        }
        req.setDetailList(detailDTOList);
        return req;
    }

    /**
     * 根据出入库消息创建逆向履约单
     */
    public CreateFulfillmentOrderReq build(WmsOutBoundMessage message, TransferOrder transferOrder){
        WarehousingOrdersQueryRequest wmsOrderQueryRequest = new WarehousingOrdersQueryRequest();
        wmsOrderQueryRequest.setWmsOrderId(message.getWmsOrderDTO().getWarehousingOrderId());
        wmsOrderQueryRequest.setIncludeFeatures(Boolean.FALSE);
//        String wmsOrderId = detailMessage.getOutboundOrderNo();
//        com.alibaba.cz.base.tool.result.Result<WarehousingOrdersQueryResponse> wmsOrder = warehousingOrderReadService.queryWarehousingOrder(wmsOrderId);
        com.alibaba.cz.base.tool.result.Result<WarehousingOrderQueryResponse> wmsOrder = warehousingOrderReadService.searchWmsOrder(wmsOrderQueryRequest);
        log.info("createFulfillmentOrderReqFactory_searchWmsOrder_result:{}",JSON.toJSONString(wmsOrder));
        if (Objects.isNull(wmsOrder) || Objects.isNull(wmsOrder.getResult()) || wmsOrder.getResult().getWarehousingOrder() == null
                ||CollectionUtils.isEmpty(wmsOrder.getResult().getWarehousingOrder().getWmsSubOrders())){
            throw new FacadeException("OTS-03-005-00-15-203");
        }
        WarehousingOrderDTO orderDTO = wmsOrder.getResult().getWarehousingOrder();
        //查出装运单信息
        List<BcShipOrderSearchRes> shipOrderList = getShipOrder(orderDTO.getWarehousingOrderId(), orderDTO.getPrevWmsOrderId());
        //当非货场提货单类型时 和 非退单, 需要有装运单, 不然就阻断.
        if (CollectionUtils.isEmpty(shipOrderList)){
            if (!AllocateOrderTypeEnum.FREIGHT_YARD_PICKUP.getType().toString().equals(transferOrder.getTransferOrderType()) &&
                !Boolean.TRUE.equals(transferOrder.getReturnOrder())){
                    //TODO 临时去掉仓间调拨校验装运单
//                !AllocateOrderTypeEnum.BETWEEN_WAREHOUSE.getType().toString().equals(transferOrder.getTransferOrderType())){
                throw new FacadeException("OTS-03-005-00-15-230","装运单查询");
            }
        }
        //如果是计划调拨 &非退单 铁运的需要等到铁运的那张装运单
        if (AllocateOrderTypeEnum.PLAN.getType().toString().equals(transferOrder.getTransferOrderType())
                && !Boolean.TRUE.equals(transferOrder.getReturnOrder())){
//            if (ToolUtil.isTrain(transferOrder.getShipMethod())){
//                if (shipOrderList.stream().noneMatch(bcShipOrderSearchRes -> Z004.equals(bcShipOrderSearchRes.getShippingType()))) {
//                    throw new FacadeException("OTS-03-005-00-15-256","铁运");
//                }
//            }
//            if (ToolUtil.isSea(transferOrder.getShipMethod())){
//                if (shipOrderList.stream().noneMatch(bcShipOrderSearchRes -> Z005.equals(bcShipOrderSearchRes.getShippingType()))) {
//                    throw new FacadeException("OTS-03-005-00-15-256","海运");
//                }
//            }
//            if (AllocateOrderShipTypeEnums.CAR.getType().equals(transferOrder.getShipMethod())){
//                if (shipOrderList.stream().noneMatch(bcShipOrderSearchRes -> Z001.equals(bcShipOrderSearchRes.getShippingType()))){
//                    throw new FacadeException("OTS-03-005-00-15-256","汽运");
//                }
//            }
        }

        CreateFulfillmentOrderReq req = new CreateFulfillmentOrderReq();
        req.setFromSys(StringUtils.isNotBlank(orderDTO.getFromSys()) ? orderDTO.getFromSys() : "APP_SAP");
        req.setBusinessType(StringUtils.isNotBlank(orderDTO.getBusinessType()) ? orderDTO.getBusinessType() :"11");
        req.setBusinessUnitCode("6000");
        req.setRequestNo(message.getWmsOrderDTO().getWarehousingOrderId());
        req.setSourceOrderNo(message.getWmsOrderDTO().getWarehousingOrderId());
        if (Boolean.TRUE.equals(transferOrder.getReturnOrder())){
            req.setRefOrderType(OrderTypeEnum.ALLOCATE_RETURN_INBOUND.getValue());
        }else {
            req.setRefOrderType(OrderTypeEnum.ALLOCATE_INBOUND.getValue());
        }
        req.setFulfillmentDirectionType(FulfillmentDirectionTypeEnum.REVERSE.getValue());
        // 判断虚拟移库 用调拨的仓判断 出入库不再创建履约单. 拦截.
        if (com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum.VIRTUAL_TRANSFER.getValue().toString().equals(transferOrder.getFulfillmentTypeCode())){
            req.setFulfillmentType(FulfillmentTypeEnum.EXTERNALWAREHOUSE_FULFILLMENT.getValue());
            log.error("CreateFulfillmentOrderReqFactory_build_virtual");
            return null;
        }else {
            req.setFulfillmentType(FulfillmentTypeEnum.BIGWAREHOUSE_FULFILLMENT.getValue());
        }
        req.setAutoSubmit(Boolean.TRUE);
        //优先级哪里来
        req.setPriority(transferOrder.getPriority() == null ? "1" : transferOrder.getPriority());
        req.setProductGroupCode(transferOrder.getProductGroupCode());

        Map<String, CargoZoneSDO> cargoZoneSDOMap = getCargoZoneSDOMap(Arrays.asList(transferOrder.getShipAreaId(), transferOrder.getReceiveAreaId(), transferOrder.getShipWarehouseId(),transferOrder.getReceiveWarehouseId())
                .stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()));
        log.info("getCargoZoneSDOMap_result:{}",JSON.toJSONString(cargoZoneSDOMap));
        Map<String, CargoZoneSDO> codeZoneSDOMap = getCargoZoneSDOMapByCodes(Arrays.asList(transferOrder.getTransferWarehouseId()).stream().filter(StringUtils::isNotBlank).collect(Collectors.toList()));
        //货场仓及退仓
        String logicShippingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipAreaId())).map(CargoZoneSDO::getCode).orElse(null);
        String logicShippingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipAreaId())).map(CargoZoneSDO::getName).orElse(null);
        String shippingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipWarehouseId())).map(CargoZoneSDO::getCode).orElse(null);
        String shippingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getShipWarehouseId())).map(CargoZoneSDO::getName).orElse(null);
        String logicReceivingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveAreaId())).map(CargoZoneSDO::getCode).orElse(null);
        String logicReceivingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveAreaId())).map(CargoZoneSDO::getName).orElse(null);
        String receivingWarehouseCode = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveWarehouseId())).map(CargoZoneSDO::getCode).orElse(null);
        String receivingWarehouseName = Optional.ofNullable(cargoZoneSDOMap.get(transferOrder.getReceiveWarehouseId())).map(CargoZoneSDO::getName).orElse(null);
        String transferWarehouseName = Optional.ofNullable(codeZoneSDOMap.get(transferOrder.getTransferWarehouseId())).map(CargoZoneSDO::getName).orElse(null);
        Map<String,String> mainFeatures = Maps.newHashMap();
        mainFeatures.put(FeaturesKey.OUT_ALLOCATE_ORDER_ID,transferOrder.getOutAllocateOrderId());
        //交货单号
        mainFeatures.put(FeaturesKey.DELIVERY_ORDER_ID,orderDTO.getDeliveryOrderId());

        if (Boolean.TRUE.equals(transferOrder.getReturnOrder())){
            req.setLogicReceivingWarehouseCode(logicShippingWarehouseCode);
            req.setLogicReceivingWarehouse(logicShippingWarehouseName);
            req.setReceivingWarehouseCode(shippingWarehouseCode);
            req.setReceivingWarehouse(shippingWarehouseName);
            mainFeatures.put(FeaturesKey.TRANSFER_ORDER_TARGET_LOGIC_WAREHOUSE_CODE,logicShippingWarehouseCode);
            if (ToolUtil.isTrainOrSea(transferOrder.getShipMethod())){
                req.setLogicShippingWarehouseCode(transferOrder.getTransferWarehouseId());
                req.setLogicShippingWarehouse(transferWarehouseName);
            }else {
                req.setLogicShippingWarehouseCode(logicReceivingWarehouseCode);
                req.setLogicShippingWarehouse(logicReceivingWarehouseName);
                req.setShippingWarehouseCode(receivingWarehouseCode);
                req.setShippingWarehouse(receivingWarehouseName);
            }
            CargoZoneSDO cargoZoneSDO = cargoZoneSDOMap.get(transferOrder.getReceiveAreaId());
            if (cargoZoneSDO != null && cargoZoneSDO.getFeature() != null){
                req.setSoldToPartyCode(cargoZoneSDO.getFeature().get("sapInternalSalesBPCode"));
                req.setShipToPartyCode(cargoZoneSDO.getFeature().get("sapInternalDeliveryBPCode"));
            }
        }else {
            req.setLogicShippingWarehouseCode(logicShippingWarehouseCode);
            req.setLogicShippingWarehouse(logicShippingWarehouseName);
            req.setShippingWarehouseCode(shippingWarehouseCode);
            req.setShippingWarehouse(shippingWarehouseName);
            mainFeatures.put(FeaturesKey.TRANSFER_ORDER_TARGET_LOGIC_WAREHOUSE_CODE,logicReceivingWarehouseCode);
            if (ToolUtil.isTrainOrSea(transferOrder.getShipMethod())){
                req.setLogicReceivingWarehouseCode(transferOrder.getTransferWarehouseId());
                req.setLogicReceivingWarehouse(transferWarehouseName);
            }else {
                req.setLogicReceivingWarehouseCode(logicReceivingWarehouseCode);
                req.setLogicReceivingWarehouse(logicReceivingWarehouseName);
                req.setReceivingWarehouseCode(receivingWarehouseCode);
                req.setReceivingWarehouse(receivingWarehouseName);
            }
            CargoZoneSDO cargoZoneSDO = cargoZoneSDOMap.get(transferOrder.getReceiveAreaId());
            if (cargoZoneSDO != null && cargoZoneSDO.getFeature() != null){
                req.setSoldToPartyCode(cargoZoneSDO.getFeature().get("sapInternalSalesBPCode"));
                req.setShipToPartyCode(cargoZoneSDO.getFeature().get("sapInternalDeliveryBPCode"));
            }
        }
        if (MapUtils.isNotEmpty(transferOrder.getBizFeatures())){
            if (StringUtils.isNotBlank(transferOrder.getBizFeatures().get(FeaturesKey.TRANSFER_OUT_BIZ_UNIT))){
                mainFeatures.put(FeaturesKey.TRANSFER_OUT_BIZ_UNIT,transferOrder.getBizFeatures().get(FeaturesKey.TRANSFER_OUT_BIZ_UNIT));
            }
            if (StringUtils.isNotBlank(transferOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT))){
                mainFeatures.put(FeaturesKey.BIZ_UNIT,transferOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT));
            }
        }
        if (MapUtils.isNotEmpty(mainFeatures)){
            req.setFeatures(FeatureUtil.toString(mainFeatures));
            req.setBizFeatures(JSONObject.toJSONString(mainFeatures));
        }
        req.setProductGroupCode(StringUtils.isNotBlank(transferOrder.getProductGroup()) ? transferOrder.getProductGroup() : "11");
        req.setChannelCode("90");
        //6000?
        req.setSalesOrganizationCode("6000");
        req.setExpectedDeliveryTime(Objects.isNull(transferOrder.getExpectedDeliveryDate()) ? null :
                DateFormatUtil.toString(transferOrder.getExpectedDeliveryDate(),"yyyy-MM-dd HH:mm:ss"));
        req.setShippingMethodCode(transferOrder.getShipMethod() == null ? null : transferOrder.getShipMethod().toString());
        req.setRemark(transferOrder.getRemark());

        //TODO 逆向履约单字段
        if (CollectionUtils.isNotEmpty(shipOrderList)){

            BcShipOrderSearchRes bcShipOrderSearchRes = shipOrderList.get(0);
            if (AllocateOrderTypeEnum.PLAN.getType().toString().equals(transferOrder.getTransferOrderType())){
//                if (ToolUtil.isTrain(transferOrder.getShipMethod())){
//                    bcShipOrderSearchRes = shipOrderList.stream().filter(f -> Z004.equals(f.getShippingType())).findFirst().orElse(shipOrderList.get(0));
//                }else if (ToolUtil.isSea(transferOrder.getShipMethod())){
//                    bcShipOrderSearchRes = shipOrderList.stream().filter(f -> Z005.equals(f.getShippingType())).findFirst().orElse(shipOrderList.get(0));
//                }else if (AllocateOrderShipTypeEnums.CAR.getType().equals(transferOrder.getShipMethod())){
//                    bcShipOrderSearchRes = shipOrderList.stream().filter(f-> Z001.equals(f.getShippingType())).findFirst().orElse(shipOrderList.get(0));
//                }
            }

            req.setShipOrderNo(bcShipOrderSearchRes.getShipOrderNo());
//            req.setContainerNo(messageData.getContainerNo());
            req.setDiverMobile(bcShipOrderSearchRes.getDiverMobile());
             req.setExpectedArrivalTime(bcShipOrderSearchRes.getExpectedDeliveryTime());
        };
        /** 以上为逆向履约单传递字段 **/
        List<CreateFulfillmentOrderDetailDTO> detailDTOList = Lists.newArrayList();
        //获取到调拨单明细 筛选出出库单上,且是履约单上的明细用来创建逆向
        for (WarehousingSubOrderDTO wmsSubOrder : orderDTO.getWmsSubOrders()) {
            /**
             * 1.出库单明细上的业务单据行号
             * 2.出入库单明细上的外部单据行号
             */

            String outAllocateOrderLineId = StringUtils.isBlank(wmsSubOrder.getFeatureMap().get("outSourceOrderLineId")) ?
                    wmsSubOrder.getFeatureMap().get("outAllocateOrderLineId") :wmsSubOrder.getFeatureMap().get("outAllocateOrderLineId");

            String bizSubOrderId = wmsSubOrder.getBizSubOrderId();
            TransferSubOrder transferSubOrder = null;
            if (StringUtils.isNotBlank(bizSubOrderId)){
                transferSubOrder = transferOrder.getDetailList().stream().filter(detail -> Objects.equals(detail.getLineNo(),bizSubOrderId))
                        .findFirst().orElse(null);
            }else if (StringUtils.isNotBlank(outAllocateOrderLineId)){
                transferSubOrder = transferOrder.getDetailList().stream().filter(detail -> Objects.equals(detail.getOutAllocateOrderLineId(),outAllocateOrderLineId))
                        .findFirst().orElse(null);
            }
            if (transferSubOrder == null){
                //TODO error
                log.error("not_match_wms_sub_order:{}",JSON.toJSONString(wmsSubOrder));
                continue;
            }
            //履约子单
            CreateFulfillmentOrderDetailDTO detailReq = new CreateFulfillmentOrderDetailDTO();
            //2024.04.02 逆向履约单 来源单行号传递出入库明细2的子单id
            detailReq.setSourceOrderLineNo(wmsSubOrder.getWmsSubOrderId());
            detailReq.setRefOrderNo(transferOrder.getTransferOrderCode());
            detailReq.setRefOrderLineNo(transferSubOrder.getLineNo() == null ? null : transferSubOrder.getLineNo());
            detailReq.setMaterialCode(transferSubOrder.getMaterialCode());
//            detailReq.setRefOrderCreateTime(transferSubOrder.getOrderCreateTime());
            detailReq.setRefOrderCreateTime(transferSubOrder.getGmtCreate() == null ? null :
                    DateFormatUtil.toString(transferSubOrder.getGmtCreate(),"yyyy-MM-dd HH:mm:ss"));
            detailReq.setProductionDate(wmsSubOrder.getDom() != null ? DateFormatUtil.formatToyyyMMdd(wmsSubOrder.getDom()) : null);
//            detailReq.setSaleQuantity(new BigDecimal(wmsSubOrder.getGoodsQuantity()).movePointLeft(3));
            //2024.04.07 这里产品认为销售数量为全额的调拨单数量
            detailReq.setSaleQuantity(new BigDecimal(transferSubOrder.getQuantity().trim()));
            detailReq.setSalesUnitCode(transferSubOrder.getUnit());
            detailReq.setQuantity(new BigDecimal(wmsSubOrder.getGoodsQuantity()).movePointLeft(3));
            detailReq.setShippedQuantity(new BigDecimal(wmsSubOrder.getGoodsQuantity()).movePointLeft(3));
            detailReq.setShippingUnit(transferSubOrder.getUnit());
            detailReq.setShippingUnitCode(transferSubOrder.getUnit());
            detailReq.setRemark(transferSubOrder.getLineRemark());
            detailReq.setClose(Boolean.TRUE.equals(transferSubOrder.getClose()) ? 1 : 0);
            detailReq.setCloseReasonCode(transferSubOrder.getCloseReasonCode());
            detailReq.setCloseReason(transferSubOrder.getCloseReason());
            //批次
            detailReq.setBatchNo(wmsSubOrder.getBatchNo());
            //TODO 写出库单的子单号的wms生成的
            Map<String,String> features = Maps.newHashMap();
            if (StringUtils.isNotBlank(wmsSubOrder.getWmsSubOrderId())){
                features.put(WMS_SUB_ORDER_ID,wmsSubOrder.getWmsSubOrderId());
            }
            if (StringUtils.isNotBlank(orderDTO.getWarehousingOrderId())){
                features.put(WMS_ORDER_ID,orderDTO.getWarehousingOrderId());
            }
            if (StringUtils.isNotBlank(transferSubOrder.getOutAllocateOrderLineId())){
                features.put(FeaturesKey.OUT_ALLOCATE_ORDER_LINE_ID,transferSubOrder.getOutAllocateOrderLineId());
            }
            //sap18位批次号
            Map<String, String> wmsSubOrderFeatureMap = MapUtils.isNotEmpty(wmsSubOrder.getFeatureMap()) ? wmsSubOrder.getFeatureMap() : Maps.newHashMap();
            if (StringUtils.isNotBlank(wmsSubOrderFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO))){
                features.put(FeaturesKey.FULL_SAP_BATCH_NO,wmsSubOrderFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO));
            }
            JSONObject bizFeaturesJsonObject = new JSONObject();
            if (MapUtils.isNotEmpty(transferSubOrder.getBizFeatures())){
                features.put(FeaturesKey.BIZ_UNIT_RATIO,transferSubOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT_RATIO));
                //渠道比例通过bizFeatures传递
                if (StringUtils.isNotBlank(transferSubOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT_RATIO))){
                    bizFeaturesJsonObject.put(FeaturesKey.BIZ_UNIT_RATIO,transferSubOrder.getBizFeatures().get(FeaturesKey.BIZ_UNIT_RATIO));
                }
            }
            if (StringUtils.isNotBlank(wmsSubOrderFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO))){
                bizFeaturesJsonObject.put(FeaturesKey.FULL_SAP_BATCH_NO,wmsSubOrderFeatureMap.get(FeaturesKey.FULL_SAP_BATCH_NO));
            }
            if (!bizFeaturesJsonObject.isEmpty()){
                detailReq.setBizFeatures(bizFeaturesJsonObject.toJSONString());
            }
            detailReq.setFeatures(FeatureUtil.toString(features));
            detailDTOList.add(detailReq);
        }
        req.setDetailList(detailDTOList);
        return req;

    }

    public Map<String,CargoZoneSDO> getCargoZoneSDOMap(List<String> idList){
        log.info("abc_request:{}",JSON.toJSONString(idList));
        Map<String,CargoZoneSDO> map = Maps.newHashMap();
        if (CollectionUtils.isEmpty(idList)){
            return map;
        }
        QueryCargoZoneRequest queryCargoZoneRequest = new QueryCargoZoneRequest();
        queryCargoZoneRequest.setWarehouseAreaIds(idList);
        queryCargoZoneRequest.setStart(0);
        queryCargoZoneRequest.setSize(idList.size());
        log.info("abcd_request:{}",JSON.toJSONString(queryCargoZoneRequest));
        com.alibaba.cz.base.tool.result.Result<ResultPager<List<CargoZoneSDO>>> resultPagerResult = cargoZoneQueryService.searchCargoZoneListByDB(queryCargoZoneRequest);
        log.info("abc_res:{}",JSON.toJSONString(resultPagerResult));
        Optional.ofNullable(resultPagerResult).map(com.alibaba.cz.base.tool.result.Result::getResult)
                .map(ResultPager::getContent).orElse(Lists.newArrayList())
                .stream().forEach(cargoZoneSDO -> map.put(cargoZoneSDO.getId(),cargoZoneSDO));
        return map;
    }

    public Map<String,CargoZoneSDO> getCargoZoneSDOMapByCodes(List<String> codes){
        log.info("code_request:{}",JSON.toJSONString(codes));
        Map<String,CargoZoneSDO> map = Maps.newHashMap();
        if (CollectionUtils.isEmpty(codes)){
            return map;
        }
        QueryCargoZoneRequest queryCargoZoneRequest = new QueryCargoZoneRequest();
        queryCargoZoneRequest.setCodes(codes);
        queryCargoZoneRequest.setStart(0);
        queryCargoZoneRequest.setSize(codes.size());
        log.info("code_request:{}",JSON.toJSONString(queryCargoZoneRequest));
        com.alibaba.cz.base.tool.result.Result<ResultPager<List<CargoZoneSDO>>> resultPagerResult = cargoZoneQueryService.searchCargoZoneListByDB(queryCargoZoneRequest);
        log.info("code_res:{}",JSON.toJSONString(resultPagerResult));
        Optional.ofNullable(resultPagerResult).map(com.alibaba.cz.base.tool.result.Result::getResult)
                .map(ResultPager::getContent).orElse(Lists.newArrayList())
                .stream().forEach(cargoZoneSDO -> map.put(cargoZoneSDO.getCode(),cargoZoneSDO));
        return map;
    }

    public List<FulfillmentGetRes> getFulfillmentInfo(String wmsOrderId) {
        log.info("CreateFulfillmentOrderReqFactory_getFulfillmentInfo_wmsOrderId:{}", wmsOrderId);
        SearchFulfullmentOrderReq req = new SearchFulfullmentOrderReq();
        req.setFulfillmentDirectionType(FulfillmentDirectionTypeEnum.REVERSE.getValue());
        req.setSourceOrderNo(wmsOrderId);

        com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result<List<FulfillmentGetRes>> result = fulfillmentOrderAbilityService.searchFulfullmentOrder(req);
        log.info("CreateFulfillmentOrderReqFactory_getFulfillmentInfo_result:{}", JSON.toJSONString(result));
        if (result == null || CollectionUtils.isEmpty(result.getResult())) {
            return null;
        }
        return result.getResult();
    }

    /**
     * 根据出入库号或交货单号查询装运单号
     * @param outBoundOrderNo
     * @param deliveryNo
     * @return
     */
    public List<BcShipOrderSearchRes> getShipOrder(String outBoundOrderNo, String deliveryNo){
        SearchBcShipOrderReq req = new SearchBcShipOrderReq();
        req.setOutBoundOrderNo(outBoundOrderNo);
//        if (StringUtils.isNotBlank(deliveryNo)){
//            if (deliveryNo.startsWith("0")){
//                req.setDeliveryNo(deliveryNo);
//            }else{
//                req.setDeliveryNo("0" + deliveryNo);
//            }
//        }
        //集成那边存储交货单去掉了0
        req.setDeliveryNo(deliveryNo);
        log.info("CreateFulfillmentOrderReqFactory_searchShipOrder_request:{}", JSON.toJSONString(req));
        com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result<List<BcShipOrderSearchRes>> shipOrder = bcShipOrderAbilityService.searchShipOrder(req);
        log.info("CreateFulfillmentOrderReqFactory_searchShipOrder_result:{}",JSON.toJSONString(shipOrder));
        if (shipOrder == null || CollectionUtils.isEmpty(shipOrder.getResult())){
            return null;
        }
        return shipOrder.getResult();
    }

    /**
     * 根据创建逆向单入参和出参,得到更新features的入参
     * @param req
     * @param res
     * @return
     */
    public UpdateFulfillmentOrderFeaturesReq build(CreateFulfillmentOrderReq req, FulfillmentOrderResponse res){
        UpdateFulfillmentOrderFeaturesReq featuresReq = new UpdateFulfillmentOrderFeaturesReq();
        featuresReq.setFulfillmentOrderNo(res.getFulfillmentOrderNo());
        featuresReq.setFeatures(req.getFeatures());
        List<UpdateFulfillmentOrderDetailFeaturesReq> subList = Lists.newArrayList();
        req.getDetailList().forEach(detail -> {
            UpdateFulfillmentOrderDetailFeaturesReq detailFeaturesReq = new UpdateFulfillmentOrderDetailFeaturesReq();
            detailFeaturesReq.setSourceOrderLineNo(detail.getSourceOrderLineNo());
            detailFeaturesReq.setFeatures(detail.getFeatures());
            subList.add(detailFeaturesReq);
        });
        featuresReq.setDetailList(subList);
        return featuresReq;
    }

}
